package com.ruleengine.endpoint.configration;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;

import com.ruleengine.endpoint.IEndpointFactory;
import com.ybt.configration.IYBTConfigration;
import com.ybt.configration.YBTConfigration;
import com.ybt.configration.YBTRuntimeConfiguration;
import com.ybt.pub.XmlUtil;

public class EndpointManager {
    private static Logger logger = Logger.getLogger(EndpointManager.class);
    private static String CONFIG_DIR = "conf" + File.separator
            + "endpointDefine.xml";
    private Map<String, EndpointDefine> map;

    private volatile static EndpointManager manager;

    private EndpointManager() {
        map = new HashMap<String, EndpointDefine>();

        CONFIG_DIR = YBTConfigration.getInstance().getProperty(
                IYBTConfigration.WORKFLOW_DEPLOY_PATH)
                + File.separator + CONFIG_DIR;

        loadFromLocal();
    }

    public static EndpointManager getInstance() {
        if (manager == null) {
            synchronized (EndpointManager.class) {
                if (manager == null) {
                    manager = new EndpointManager();
                }
            }
        }
        return manager;
    }

    /**
     * 根据xml标签tag名，初始化ITask对象.
     * @param tagName
     *            工作流节点tag名
     * @return 工作流节点解析器
     */
    public IEndpointFactory createEndpointFactory(String type) {
        EndpointDefine define = map.get(type);
        if (define == null) {
            // tag名不支持
            throw new RuntimeException("unsupport task tag, tagName is = "
                    + type);
        }

        try {
            // 初始化工作流任务
            Class c = Class.forName(define.factory);
            return (IEndpointFactory) c.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("initialize task error :"
                    + define.factory, e);
        }
    }

    private void loadFromLocal() {

        File file = new File(CONFIG_DIR);
        if (!file.exists()) {
            throw new RuntimeException("can't find the configration file : "
                    + CONFIG_DIR);
        }

        try {
            Document doc = XmlUtil.loadXml(CONFIG_DIR, YBTRuntimeConfiguration
                    .getInstance().getConfigFileCharset());
            List<Element> tasks = doc.getRootElement().elements("endpoint");
            for (Element et : tasks) {
                String type = et.attributeValue("type");
                String factory = et.element("factory").getTextTrim();
                map.put(type, new EndpointDefine(type, factory));
                
                logger.debug("load endpoint define [" + type + " : " + factory
                        + "]");
            }
        } catch (Exception e) {
            throw new RuntimeException("parse configration file error : "
                    + CONFIG_DIR, e);
        }
    }

    private class EndpointDefine {
        String type;
        String factory;

        public EndpointDefine(String type, String factory) {
            super();
            this.type = type;
            this.factory = factory;
        }
    }
}
